/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package questionbook.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.openrdf.model.Statement;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.model.vocabulary.RDFS;
import questionbook.Configuration.QuestionbookConfiguration;
import questionbook.exception.IndividualAlreadyExistsException;
import questionbook.model.Category;
import questionbook.model.Person;
import questionbook.model.Question;
import questionbook.service.common.GenericServiceImpl;
import questionbook.standard.Qbook;

/**
 *
 * @author stefanstift
 */
public class QuestionServiceBean extends GenericServiceImpl implements QuestionService {

    private PersonService personService = new PersonServiceBean();
    private CategoryService categoryService = new CategoryServiceBean();

    public void persist(Question q) {

        this.storeManager.getStore().add(q.getUri(), RDF.TYPE, Qbook.getInstance().getQuestionURI());
        this.storeManager.getStore().add(q.getAsker().getUri(), Qbook.getInstance().getAsksURI(), q.getUri());
        this.storeManager.getStore().add(q.getUri(), RDFS.LABEL, q.getTextLiteral());
        this.storeManager.getStore().add(q.getUri(), Qbook.getInstance().getHasCategoryURI(), q.getCategory().getUri());
        this.storeManager.getStore().add(q.getUri(), Qbook.getInstance().getCreatedAtURI(), q.getCreatedAtLiteral());
        this.storeManager.getStore().add(q.getUri(), Qbook.getInstance().getHasTitleURI(), q.getTitleLiteral());
    }

    public List<Question> getAll() {

        List<Question> questionList = new ArrayList<Question>();

        List<Map> resultList = this.storeManager.getStore().runSPARQL("SELECT ?question ?text ?asker ?category ?title ?createdAt"
                + " WHERE { ?question <" + RDF.TYPE.toString() + "> <" + Qbook.getInstance().getQuestionURI() + "> ."
                + " ?question <" + RDFS.LABEL + "> ?text ."
                + " ?asker <" + Qbook.getInstance().getAsksURI() + "> ?question ."
                + " ?question <" + Qbook.getInstance().getHasTitleURI() + "> ?title ."
                + " ?question <" + Qbook.getInstance().getHasCategoryURI() + "> ?category ."
                + " ?question <" + Qbook.getInstance().getCreatedAtURI() + "> ?createdAt "
                + "}");


        for(Map m : resultList)
        {
            Question q = new Question(((Value) m.get("question")).stringValue());
            q.setTitle(((Value) m.get("title")).stringValue());
            q.setText(((Value) m.get("text")).stringValue());
            q.setCreatedAt(((Value) m.get("createdAt")).stringValue());

            URI asker = this.storeManager.getStore().getURIref(((Value) m.get("asker")).stringValue());
            q.setAsker(this.personService.get(asker));

            URI cat = this.storeManager.getStore().getURIref(((Value) m.get("category")).stringValue());
            q.setCategory(this.categoryService.get(cat));

            if(!questionList.contains(q))
                questionList.add(q);

        }

        return questionList;
    }

     public List<Question> getByCategory(Category c) {

        List<Question> questionList = new ArrayList<Question>();

        List<Map> resultList = this.storeManager.getStore().runSPARQL("SELECT ?question ?text ?asker ?title ?createdAt"
                + " WHERE { ?question <" + RDF.TYPE.toString() + "> <" + Qbook.getInstance().getQuestionURI() + "> ."
                + " ?question <" + RDFS.LABEL + "> ?text ."
                + " ?question <" + Qbook.getInstance().getHasTitleURI() + "> ?title ."
                + " ?asker <" + Qbook.getInstance().getAsksURI() + "> ?question ."
                + " ?question <" + Qbook.getInstance().getHasCategoryURI() + "> <" + c.getUri().stringValue() + "> ."
                + " ?question <" + Qbook.getInstance().getCreatedAtURI() + "> ?createdAt "
                + "}");


        for(Map m : resultList)
        {
            Question q = new Question(((Value) m.get("question")).stringValue());
            q.setText(((Value) m.get("text")).stringValue());
            q.setTitle(((Value) m.get("title")).stringValue());
            q.setCreatedAt(((Value) m.get("createdAt")).stringValue());
            q.setCategory(c);

            URI asker = this.storeManager.getStore().getURIref(((Value) m.get("asker")).stringValue());
            q.setAsker(this.personService.get(asker));

            if(!questionList.contains(q))
                questionList.add(q);
        }

        return questionList;
    }

    public Question get(URI uri)
    {
        Question q = new Question(uri);

        List<Statement> tx = this.storeManager.getStore().tuplePattern(uri, RDFS.LABEL, null);
        List<Statement> tl = this.storeManager.getStore().tuplePattern(uri, Qbook.getInstance().getHasTitleURI(), null);
        List<Statement> ct = this.storeManager.getStore().tuplePattern(uri, Qbook.getInstance().getHasCategoryURI(), null);
        List<Statement> ca = this.storeManager.getStore().tuplePattern(uri, Qbook.getInstance().getCreatedAtURI(), null);
        List<Statement> as = this.storeManager.getStore().tuplePattern(null, Qbook.getInstance().getAsksURI(), uri);
 

        if(tx != null && tx.size() > 0)
            q.setText(tx.get(0).getObject().stringValue());
        if(tl != null && tl.size() > 0)
            q.setTitle(tl.get(0).getObject().stringValue());
        if(ct != null && ct.size() > 0)
        {
            URI cat = this.storeManager.getStore().getURIref(ct.get(0).getObject().stringValue());
            q.setCategory(this.categoryService.get(cat));
        }
        if(ca != null && ca.size() > 0)
            q.setCreatedAt(ca.get(0).getObject().stringValue());

        if(as != null && as.size() > 0)
        {
            URI asker = this.storeManager.getStore().getURIref(as.get(0).getSubject().stringValue());
            q.setAsker(this.personService.get(asker));
        }

        return q;
    }

     public Question getIdentifiedQuestion() throws IndividualAlreadyExistsException{

        int i = 0;
        String questionBase = "/qbQuestion";
        Date d = new Date();
        String timestamp = Long.toString(d.getTime());

        String id = QuestionbookConfiguration.getInstance().getBaseURL() + questionBase + timestamp;
        URI uri = this.storeManager.getStore().getURIref(id);

        List check = this.storeManager.getStore().tuplePattern(uri, null, null);

        while(check != null || !check.isEmpty())
        {
            if(i == 10)
            {
                break;
            }

            d = new Date();
            timestamp = Long.toString(d.getTime());
            id = QuestionbookConfiguration.getInstance().getBaseURL() + questionBase + timestamp;
            uri = this.storeManager.getStore().getURIref(id);

            check = this.storeManager.getStore().tuplePattern(uri, null, null);

            i++;
        }

        if(check == null || check.isEmpty())
        {
            Question q = new Question(uri);
            q.setCreatedAt(new Date());
            return q;
        }

        throw new IndividualAlreadyExistsException("Tried to create Question with URI " + id + " - but it already exists in the Store");
    }

    public void delete(Question q) {
         this.storeManager.getStore().removeTuplePattern(q.getUri(), null, null);
    }

    public void linkQuestions(Question q1, Question q2) {

        this.storeManager.getStore().add(q1.getUri(), Qbook.getInstance().getRelatedQuestionURI(), q2.getUri());
        this.storeManager.getStore().add(q2.getUri(), Qbook.getInstance().getRelatedQuestionURI(), q1.getUri());
    }

    public List<Question> getLinkedQuestions(Question q)
    {
        List<Question> questionList = new ArrayList<Question>();

        List<Statement> rel = this.storeManager.getStore().tuplePattern(q.getUri(), Qbook.getInstance().getRelatedQuestionURI(), null);

        for(Statement s : rel)
        {
            URI uri = this.storeManager.getStore().getURIref(rel.get(0).getObject().stringValue());
            Question question = this.get(uri);

            if(!questionList.contains(question))
                questionList.add(question);
        }

        return questionList;
    }

//    public List<Question> getLinkedQuestions(Question q) {
//
//        System.out.println("linked question for " + q.getUri().stringValue());
//
//        List<Question> questionList = new ArrayList<Question>();
//
//        List<Map> resultList = this.storeManager.getStore().runSPARQL("SELECT ?question ?text ?asker ?title ?category ?createdAt"
//                + " WHERE { ?question <" + RDF.TYPE + "> <" + Qbook.getInstance().getQuestionURI() + "> ."
//                + " ?question <" + RDFS.LABEL + "> ?text ."
//                + " ?question <" + Qbook.getInstance().getHasTitleURI() + "> ?title ."
//                + " ?asker <" + Qbook.getInstance().getAsksURI() + "> ?question ."
//                + " ?question <" + Qbook.getInstance().getHasCategoryURI() + "> ?category ."
//                + " ?question <" + Qbook.getInstance().getCreatedAtURI() + "> ?createdAt ."
//                + " { ?question <" + Qbook.getInstance().getRelatedQuestionURI() + "> <" + q.getUri() + "> } UNION "
//                + " { <" + q.getUri() + "> <" + Qbook.getInstance().getRelatedQuestionURI() + "> ?question } "
//                + "}");
//
//        for(Map m : resultList)
//        {
//            Question question = new Question(((Value) m.get("question")).stringValue());
//            question.setText(((Value) m.get("text")).stringValue());
//            question.setCreatedAt(((Value) m.get("createdAt")).stringValue());
//            question.setTitle(((Value) m.get("title")).stringValue());
//
//            URI asker = this.storeManager.getStore().getURIref(((Value) m.get("asker")).stringValue());
//            question.setAsker(this.personService.get(asker));
//
//            URI cat = this.storeManager.getStore().getURIref(((Value) m.get("category")).stringValue());
//            question.setCategory(this.categoryService.get(cat));
//
//            if(!questionList.contains(q))
//                questionList.add(q);
//        }
//
//        return questionList;
//    }

    public void unlinkQuestions(Question q1, Question q2) {
        this.storeManager.getStore().removeTuplePattern(q1.getUri(), Qbook.getInstance().getRelatedQuestionURI(), q2.getUri());
        this.storeManager.getStore().removeTuplePattern(q2.getUri(), Qbook.getInstance().getRelatedQuestionURI(), q1.getUri());
    }

    public List<Question> getByPerson(Person p) {

        List<Question> questionList = new ArrayList<Question>();

        List<Map> resultList = this.storeManager.getStore().runSPARQL("SELECT ?question ?text ?title ?category ?createdAt"
                + " WHERE { ?question <" + RDF.TYPE.toString() + "> <" + Qbook.getInstance().getQuestionURI() + "> ."
                + " ?question <" + RDFS.LABEL + "> ?text ."
                + " ?question <" + Qbook.getInstance().getHasTitleURI() + "> ?title ."
                + " <" + p.getUri() + "> <" + Qbook.getInstance().getAsksURI() + "> ?question ."
                + " ?question <" + Qbook.getInstance().getHasCategoryURI() + "> ?category ."
                + " ?question <" + Qbook.getInstance().getCreatedAtURI() + "> ?createdAt "
                + "}");


        for(Map m : resultList)
        {
            Question q = new Question(((Value) m.get("question")).stringValue());
            q.setText(((Value) m.get("text")).stringValue());
            q.setTitle(((Value) m.get("title")).stringValue());
            q.setCreatedAt(((Value) m.get("createdAt")).stringValue());

            q.setAsker(p);

            URI cat = this.storeManager.getStore().getURIref(((Value) m.get("category")).stringValue());
            q.setCategory(this.categoryService.get(cat));

            if(!questionList.contains(q))
                questionList.add(q);
        }

        return questionList;
    }

}
